package com.duckygo.towerdefense.game.scenes;

import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.hardware.SensorEvent;
import android.opengl.GLU;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;

import com.duckygo.towerdefense.game.sprites.ISprite;
import com.duckygo.towerdefense.game.sprites.Sprite;

public class SceneManager implements ISprite, ISceneManager {
	
	public static int WIDTH;
	public static int HEIGHT;
	public static float DENSITY = 1;
	
	private static final int MAX_SPRITES = 500;
	
	private static final Sprite[] displayList = new Sprite[MAX_SPRITES] ;
	
	private static SceneManager instance;
	
	public static final Sprite root = new Sprite();
	
	public static void setInstance(SceneManager scene) {
		instance = scene;
	}
	
	public static SceneManager getInstance() {
		return instance;
	}
	
	public static void updateGL(GL10 gl, int width, int height) {

		WIDTH = width;
		HEIGHT = height;
		
		gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
		
		gl.glDisable(GL10.GL_DITHER);
	    gl.glDisable(GL10.GL_LIGHTING);
		
		Log.w("SceneManager", "Updating gl canvas " + width + "x" + height);
		
		gl.glEnable(GL10.GL_BLEND);	
		gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
		
//		gl.glEnable(GL10.GL_DEPTH_TEST);
//		gl.glDepthFunc(GL10.GL_NEAREST);

		
		gl.glEnable(GL10.GL_TEXTURE_2D);	

	    gl.glShadeModel(GL10.GL_FLAT);
	 
	    gl.glViewport(0, 0, width, height);
	 
	    gl.glMatrixMode(GL10.GL_PROJECTION);
	    gl.glLoadIdentity();
	    
	    float ratio = (float)width / (float)height;
	    GLU.gluPerspective(gl, 45.0f,
              ratio,
              0.1f, 100.0f);
	    
	    gl.glFrustumf(-ratio, ratio, -1, 1, 0, 10);
	    
		gl.glMatrixMode(GL10.GL_MODELVIEW);
		gl.glLoadIdentity();
		gl.glTranslatef(0, 0, -2);
		gl.glRotatef(-45, 1f, 0f, 0f);	
	   	
	}

	public boolean invalidDisplayList;

	private int k;
	

	public void register(GL10 gl, Context context) {
		WIDTH = context.getResources().getDisplayMetrics().widthPixels;
		HEIGHT = context.getResources().getDisplayMetrics().heightPixels;
		
		DENSITY = context.getResources().getDisplayMetrics().density;
	}

	public void unregister() {
	}
	
	private void validateDisplayList(Sprite root) {
		for (int i = 0; i < root.children.size(); i++) {
			Sprite sprite = root.children.get(i);
			
			displayList[k++] = sprite;
			if (sprite.children.size() > 0)	validateDisplayList(sprite);
		}
	}
	
	@Override
	public void draw(GL10 gl) {
		if (invalidDisplayList) {
			k = 0;
			validateDisplayList(root);
			invalidDisplayList = false;
		}

		gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);		
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
		
		    
		for (int i = 0; i < k; i++) {
			if (!displayList[i].visible) {
				continue;
			}
			
			gl.glPushMatrix();
			if (displayList[i] != null)	displayList[i].draw(gl);
			gl.glPopMatrix();
		}
	}

	@Override
	public void update(long time) {
		for (int i = 0; i < MAX_SPRITES; i++) {
			if (displayList[i] != null)	displayList[i].update(time);
		}
	}

	public boolean onTouchEvent(MotionEvent event) {
		for (int i = MAX_SPRITES - 1; i >= 0; i--) {
			if (displayList[i] != null && displayList[i].onTouchEvent(event)) return true;
		}
		return false;
	}

	public void onSensorEvent(SensorEvent sensor) {
		for (int i = 0; i < MAX_SPRITES; i++) {
			if (displayList[i] != null)	displayList[i].onSensorEvent(sensor);
		}
	}

	public boolean onKeyEvent(KeyEvent event, int keyCode) {
		for (int i = MAX_SPRITES - 1; i >= 0; i--) {
			if (displayList[i] != null && displayList[i].onKeyEvent(event, keyCode)) return true;
		}
		return false;
	}
}
